package com.shyroke.calculation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import entity.GroupDesicionDto;

/**
 * 计算TOPSIS
 * 
 * @author shyroke
 *
 */
public class TopSisCal {

	/**
	 * 正理想解
	 */
	private List<Double> zhengList = Arrays.asList(1.00, 0.00, 0.00);

	/**
	 * 负理想解
	 */
	private static final List<Double> fuList = Arrays.asList(0.00, 1.00, 1.00);

	/**
	 * 计算D+
	 * 
	 * @param attributeWeight
	 * @param desicionDtos
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	public Map<String,Double> getDPlus(Map<String, Double> attributeWeight, List<GroupDesicionDto> desicionDtos,String type) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		Map<String,Double> resultMap = new HashMap();

		List<List<Double>> x1List = new ArrayList<>();
		List<List<Double>>  x2List = new ArrayList<>();
		List<List<Double>>  x3List = new ArrayList<>();
		
		for (int i = 1; i <= 3; i++) {// 3个方案

			
			for(GroupDesicionDto desicionDto:desicionDtos ) {
				Method method = desicionDto.getClass().getMethod("getX"+i+"info");
				List<Double> list =(List<Double>) method.invoke(desicionDto);
				
				if(i==1) {
					x1List.add(list);
				}else if(i==2) {
					x2List.add(list);
				}else if(i==3) {
					x3List.add(list);
				}
			}
		}
		
		if("D+".equals(type)) {
			
			resultMap.put("x1", this.getDPlust(attributeWeight,x1List,"D+"));
			resultMap.put("x2", this.getDPlust(attributeWeight,x2List,"D+"));
			resultMap.put("x3", this.getDPlust(attributeWeight,x3List,"D+"));
			
		}else if("D-".equals(type)) {
			resultMap.put("x1", this.getDPlust(attributeWeight,x1List,"D-"));
			resultMap.put("x2", this.getDPlust(attributeWeight,x2List,"D-"));
			resultMap.put("x3", this.getDPlust(attributeWeight,x3List,"D-"));
		}
		

		return resultMap;

	}

	
	/**
	 * 计算D+值
	 * @param attributeWeight
	 * @param x1List  某个方案的所有属性的中智集
	 * @return
	 */
	private Double getDPlust(Map<String, Double> attributeWeight, List<List<Double>> xList,String type) {
		Double result = 0.00;
		List<Double> distance = new ArrayList<>();
		for(List<Double> x:xList) {
			
			List<Double> distance_TIF = new ArrayList<>();
			
			for(int i=0;i<x.size();i++) {
				
				if("D+".equals(type)) {
					distance_TIF.add(Math.pow((x.get(i)-zhengList.get(i)), 2));
				}else if("D-".equals(type)) {
					distance_TIF.add(Math.pow((x.get(i)-fuList.get(i)), 2));
				}
					
			}
			
			Double avgTIF = 0.00;
			for(Double dis : distance_TIF) {
				avgTIF = avgTIF+dis;
			}
			avgTIF = Double.valueOf(new DecimalFormat("#.000").format(avgTIF/3));
			
			distance.add(Math.sqrt(avgTIF));
		}
		
	
		
		for(int i=0;i<distance.size();i++ ) {
			
			if(i==0) {  //表示属性一
				result = result + (attributeWeight.get("c1") * distance.get(i) );
			}else if(i==1) {
				result = result + (attributeWeight.get("c2") * distance.get(i) );
			}
			else if(i==2) {
				result = result + (attributeWeight.get("c3") * distance.get(i) );
			}
				
			else if(i==3) {
				result = result + (attributeWeight.get("c4") * distance.get(i) );
			}
				
			
		}
		
		
		return result;
	}


	/**
	 * 计算TOPSIS的C值
	 * @param d_plust
	 * @param d_jian
	 * @return
	 */
	public Map<String, Double> getC(Map<String, Double> d_plust, Map<String, Double> d_jian) {
		
		Map<String, Double> resultMap = new HashMap<>();
		
		for(String fangan:d_plust.keySet()) {
			
			double sum = d_plust.get(fangan)+d_jian.get(fangan);
			
			resultMap.put(fangan, Double.valueOf(new DecimalFormat("#.000").format(d_jian.get(fangan)/sum)));
			
		}
		
		
		return resultMap;
	}

/**
 * 根据各个方案的C值得出结论
 * C值最大的为最佳方案
 * @param c_X
 * @return
 */
	public String getResult(Map<String, Double> c_X) {
		String result=null;
		double max=0.00;
		
		for(String fangan:c_X.keySet()) {
			max =  max<c_X.get(fangan)?c_X.get(fangan):max;
		}
		
		for(String fangan:c_X.keySet()) {
			if(max == c_X.get(fangan)) {
				result = fangan;
				break;
			}
		}
			
		
		return result;
	}

}
